#include "bsp_e53.h"
#include "lz_hardware.h"

#include "bsp_I2C.h"

#define BH1750_ADDR     0x23
#define SHT30_ADDR      0x44

// static I2cBusIo m_ia_i2c0m2 = {
//     .scl = {.gpio = GPIO0_PA1, .func = MUX_FUNC3, .type = PULL_NONE, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_KEEP, .val = LZGPIO_LEVEL_KEEP},
//     .sda = {.gpio = GPIO0_PA0, .func = MUX_FUNC3, .type = PULL_NONE, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_KEEP, .val = LZGPIO_LEVEL_KEEP},
//     .id = FUNC_ID_I2C0,
//     .mode = FUNC_MODE_M2,
// };

static void e53_ia_io_init(void)
{
    uint32_t ret = LZ_HARDWARE_FAILURE;

    LzGpioInit(GPIO0_PA2);  //紫光灯
    LzGpioInit(GPIO1_PD0);  //电机

    //GPIO0_PA2输出模式
    ret = LzGpioSetDir(GPIO0_PA2, LZGPIO_DIR_OUT);
    if(ret != LZ_HARDWARE_SUCCESS)
    {
        printf("set GPIO0_PA2 Direction failed!\n");
    }

    //设置GPIO1_PD0为输出模式
    ret = LzGpioSetDir(GPIO1_PD0, LZGPIO_DIR_OUT);
    if(ret != LZ_HARDWARE_SUCCESS)
    {
        printf("set GPIO0_PD0 Direction failed!\n");
    }

    // //初始化I2C
    // if(I2cIoInit(m_ia_i2c0m2) != LZ_HARDWARE_SUCCESS)
    // {
    //     printf("init I2C I2C0 io failed\n");
    // }
    // //设置I2C时钟频率为100K
    // if(LzI2cInit(IA_I2C0, 100000) != LZ_HARDWARE_SUCCESS)
    // {
    //     printf("init I2C I2C0 failed!\n");
    // }
}

//写命令初始化BH1750
static void init_bh1750(void)
{
    uint8_t send_data[1] = {0x01};
    uint32_t send_len = 1;

    LzI2cWrite(IA_I2C0, BH1750_ADDR, send_data, send_len);
}

//初始化SHT30，设置测量周期
static void init_sht30(void)
{
    uint8_t send_data[2] = {0x22, 0x36};
    uint32_t send_len = 2;

    LzI2cWrite(IA_I2C0, SHT30_ADDR, send_data, send_len);
}

void e53_ia_init(void)
{
    e53_ia_io_init();
    init_bh1750();
    init_sht30();
}

//启动BH1750
static void start_bh1750()
{
    uint8_t send_data[1] = {0x10};
    uint32_t send_len = 1;

    LzI2cWrite(IA_I2C0, BH1750_ADDR, send_data, send_len);
}

//校验
static uint8_t sht30_check_crc(uint8_t *data, uint8_t nbrOfBytes, uint8_t checksum)
{
    uint8_t crc = 0xFF;
    uint8_t bit = 0;
    uint8_t byteCtr;
    const int16_t POLYNOMIAL = 0x131;

    //校验和
    for(byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
    {
        crc ^= (data[byteCtr]);
        for(bit = 8; bit > 0; --bit)
        {
            if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
            else crc = (crc << 1);
        }
    }

    if(crc != checksum)
        return 1;
    else
        return 0;
}

//温度计算(原始数据换算)
static float sht30_calc_temperature(uint16_t u16sT)
{
    float t = 0;

    u16sT &= ~0x0003; //clear bits 

    /*calculate temperature [℃]*/
    /*T = -45 + 175 * rawValue / (2^16-1)*/
    t = (175 * (float)u16sT / 65535 - 45);

    return t;
}

static float sht30_calc_RH(uint16_t u16sRH)
{
    float h = 0;

    u16sRH &= ~0x0003;  //clear bits

    /*calculate relative humidity [%RH]*/
    /*RH = rawValue / (2^16-1) * 10*/
    h = (100 * (float)u16sRH / 65535); //求百分比

    return h;
}

void e53_ia_read_data(e53_data_t *pData)
{
    //bh1750
    uint8_t recv_data[2] = {0};
    uint32_t receive_len = 2;
    uint8_t rc;
    //sht30 温度、湿度
    uint8_t data[3];
    uint16_t tmp;
    uint8_t SHT30_Data_Buffer[6];// 0,1 is 温度， 4,5 is 湿度
    uint8_t send_data[2] = {0xE0, 0x00};
    uint32_t send_len = 2;

    //取光照
    start_bh1750();
    LOS_Msleep(180);
    LzI2cRead(IA_I2C0, BH1750_ADDR, recv_data, receive_len);
    pData->luminance = (float)(((recv_data[0]<<8) + recv_data[1]) / 1.2);

    memset(SHT30_Data_Buffer, 0, 6);
    LzI2cWrite(IA_I2C0, SHT30_ADDR, send_data, send_len);
    receive_len = 6;
    LzI2cRead(IA_I2C0, SHT30_ADDR, SHT30_Data_Buffer, receive_len);

    //温度
    data[0] = SHT30_Data_Buffer[0];
    data[1] = SHT30_Data_Buffer[1];
    data[2] = SHT30_Data_Buffer[2];
    rc = sht30_check_crc(data, 2, data[2]);
    if(!rc)
    {
        tmp =((uint16_t)data[0] << 8) | data[1];
        pData->temperature = sht30_calc_temperature(tmp);
    }

    //湿度
    data[0] = SHT30_Data_Buffer[3];
    data[1] = SHT30_Data_Buffer[4];
    data[2] = SHT30_Data_Buffer[5];
    rc = sht30_check_crc(data, 2, data[2]);
    if(!rc)
    {
        tmp = ((uint16_t)data[0] << 8) | data[1];
        pData->humidity = sht30_calc_RH(tmp);
    }
}

int light_set(int state)
{
    printf("[light_set] enter light_set, status: %d.\n", state);

    if(1 == state)
    {
        LzGpioSetVal(GPIO0_PA2, LZGPIO_LEVEL_HIGH);
    }
    else if(0 == state)
    {
        LzGpioSetVal(GPIO0_PA2, LZGPIO_LEVEL_LOW);
    }

    return 0;
}

int motor_set(int state)
{
    printf("[motor_set] enter motor_set, status: %d.\n", state);

    if(1 == state)
    {
        LzGpioSetVal(GPIO1_PD0, LZGPIO_LEVEL_HIGH);
    }
    else if(0 == state)
    {
        LzGpioSetVal(GPIO1_PD0, LZGPIO_LEVEL_LOW);
    }

    return 0;
}
